<?php

namespace fakis\config;

use fakis\config\adapters\AdapterInterface;
use fakis\config\adapters\FileAdapter;
use yii\helpers\ArrayHelper;

/**
 * 配置接口
 *
 * @property string $symbol
 * @property-read Model $model
 *
 * @author Fakis <fakis738@qq.com>
 */
class Component extends \yii\base\Component
{
    /**
     * @var AdapterInterface|array|string
     */
    public $adapter = ['class' => FileAdapter::class];

    /**
     * @var string
     */
    public $target;

    /**
     * @var string
     */
    private $_symbol;

    /**
     * @var array
     */
    private $_models = [];

    /**
     * 切换目标
     * @param string $class
     * @return $this
     */
    public function target($class)
    {
        $this->target = $class;
        return $this;
    }

    /**
     * 返回标识
     * @return string
     */
    public function getSymbol(): string
    {
        $hash = sprintf('%x', crc32($this->target));
        return $this->_symbol ? $this->_symbol . '_' . $hash : $hash;
    }

    /**
     * 设置标识
     * @param callable|string $symbol
     */
    public function setSymbol($symbol)
    {
        $this->_symbol = is_callable($symbol) ? $symbol($this) : $symbol;
    }

    /**
     * 取得配置属性值
     * @param string $attribute
     * @param mixed $default
     * @return mixed|null
     */
    public function get(string $attribute, $default = null)
    {
        return ArrayHelper::getValue($this->model, $attribute, $default);
    }

    /**
     * 取得配置所有属性值
     * @return array
     */
    public function all()
    {
        return $this->model->attributes;
    }

    /**
     * 返回配置模型
     * @return Model
     */
    public function getModel()
    {
        if (isset($this->_models[$this->symbol])) {
            return $this->_models[$this->symbol];
        }

        return $this->_models[$this->symbol] = new Model($this);
    }

    /**
     * 取得配置模型
     * @return Model
     */
    public function model(): Model
    {
        if (isset($this->_models[$this->symbol])) {
            return $this->_models[$this->symbol];
        }

        return $this->_models[$this->symbol] = new Model($this);
    }

    /**
     * 保存配置
     * @param array $attributes
     * @return bool
     */
    public function store($attributes): bool
    {
        return $this->model->load($attributes) && $this->model->store();
    }

    /**
     * 还原配置默认值
     * @param array|null $names
     * @return bool
     */
    public function restore(array $names = null): bool
    {
        return $this->model->restore($names);
    }
}